package com.ubtechinc.cruzr.launcher2.model.helper;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.text.TextUtils;

import com.ubtechinc.cruzr.launcher2.R;
import com.ubtechinc.cruzr.launcher2.callback.AppListener;
import com.ubtechinc.cruzr.launcher2.callback.SchedulersListener;
import com.ubtechinc.cruzr.launcher2.callback.SettingListener;
import com.ubtechinc.cruzr.launcher2.model.AppManger;
import com.ubtechinc.cruzr.launcher2.model.dao.FilterDao;
import com.ubtechinc.cruzr.launcher2.model.db.InitialTools;
import com.ubtechinc.cruzr.launcher2.model.entity.AppInfo;
import com.ubtechinc.cruzr.launcher2.utlis.UbtCantans;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

public class LoadHelper {
    private static List<String> filterlist = new ArrayList<>();
    private static List<String> customizationlist = new ArrayList<>();
    private static List<AppInfo> mAppList = new ArrayList<>();
    private static HashMap<String, String> mIconMap = new HashMap<>();
    public static boolean isLoading = false;
    private static List<String> firstList = new ArrayList<>();
    private static List<String> visitlist = new ArrayList<>();

    @SuppressLint("CheckResult")
    public synchronized static void load(final Context context, final PackageManager pm, final AppListener listener,
                                         final boolean isinit, final boolean isadmini) {
        io.reactivex.Observable.create(new ObservableOnSubscribe<List<ResolveInfo>>() {
            @Override
            public void subscribe(ObservableEmitter<List<ResolveInfo>> e) {
                isLoading = true;
                initFilter(context);
                initFirst(context);
                initVisitList(context);
                e.onNext(getAllApps(pm));
                e.onComplete();
            }
        }).map(new Function<List<ResolveInfo>, List<AppInfo>>() {
            @Override
            public List<AppInfo> apply(List<ResolveInfo> resolveInfos) {
                return mapList(context, pm, resolveInfos, AppManger.get().getSttingsListener(), isadmini);
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<List<AppInfo>>() {
            @Override
            public void accept(List<AppInfo> appInfos) {
                if (listener != null) {
                    if (isinit) {
                        listener.appInit(appInfos);
                    } else {
                        listener.appUpdate(appInfos);
                    }
                }
            }
        });
    }

    private static void initFirst(Context context) {
        if (firstList.isEmpty()) {
            String first[] = context.getResources().getStringArray(R.array.firt_page_list);
            firstList = Arrays.asList(first);
        }
    }

    private static void initVisitList(Context context) {
        if (visitlist.isEmpty()) {
            String visit[] = context.getResources().getStringArray(R.array.visit_list);
            visitlist = Arrays.asList(visit);
        }
    }

    private static void initFilter(Context context) {
        if (InitialTools.getInt(context, "firstTime") == 0) {
            InitialTools.insertOrigialData();
            InitialTools.putInt(context, "firstTime", 1);
        }
        String filter[] = context.getResources().getStringArray(R.array.filter_list);
        String custom[] = context.getResources().getStringArray(R.array.customization_list);
        filterlist = Arrays.asList(filter);
        customizationlist = Arrays.asList(custom);
        initIconMap(context);
    }

    private static List<ResolveInfo> getAllApps(PackageManager pm) {
        final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        return pm.queryIntentActivities(mainIntent, 0);
    }

    private static List<AppInfo> mapList(Context context, PackageManager pm, List<ResolveInfo> resolveInfos,
                                         final SettingListener listener, boolean isadmini) {
        UbtCantans.CLOCK_VISIBLE = isadmini;
        int third_index = -1;
        List<AppInfo> list = new ArrayList<>();
        mAppList.clear();
        for (ResolveInfo rinfo : resolveInfos) {
            String pkg = rinfo.activityInfo.packageName;
            String activityname = rinfo.activityInfo.name;
            if (isFilterList(pkg)) {
                continue;
            }
            int id = isAdminiList(activityname);
            AppInfo info = new AppInfo();
            info.isAdminiApp = (id != -1);
            info.packagename = pkg;
            info.activityname = activityname;
            info.iconname = mIconMap.get(activityname);
            info.appname = rinfo.loadLabel(pm).toString();
            info.res = rinfo;
            //
            info.isSystemApp = isSystemApp(context, pkg);

            if (UbtCantans.POWER_CLOCK_PKG.equals(pkg) && (!info.isAdminiApp || isadmini)) {
                info.isclock = true;
                UbtCantans.CLOCK_VISIBLE = true;
            } else if (UbtCantans.POWER_SETTINGS_PKG.equals(pkg)) {
                info.ispower = true;
            }
            if (isadmini) {
                if (!info.isSystemApp) {
                    third_index++;
                    info.thirdAppIndex = third_index;
                }
                list.add(info);
            } else {
                if (id == -1) {
                    if (!info.isSystemApp) {
                        third_index++;
                        info.thirdAppIndex = third_index;
                    }
                    list.add(info);
                }
            }
            if (id != -1) {
                info.id = id;
            }
            if (!info.isSystemApp || visitlist.contains(info.packagename)) {
                mAppList.add(info);
            }
        }
        OrderList r = new OrderList();
        Collections.sort(list, r);
        if (listener != null) {
            RxAndroidUtils.runOnMain(new SchedulersListener() {
                @Override
                public void onMain() {
                    listener.onAllApppdate(mAppList);
                }
            });
        }
        isLoading = false;
        return list;
    }

    private static boolean isFilterList(String packagename) {
        if (TextUtils.isEmpty(packagename)) {
            return false;
        }
        if (filterlist == null || filterlist.size() == 0) {
            return false;
        }
        for (String pkg : filterlist) {
            if (packagename.equals(pkg)) {
                return true;
            }
        }
        return false;
    }

    private static int isAdminiList(String activityname) {
        if (TextUtils.isEmpty(activityname)) {
            return -1;
        }
        AppInfo info = FilterDao.get().getAppInfo(activityname);
        return info != null ? info.id : -1;
    }

    private static void initIconMap(Context context) {
        String icons[] = context.getResources().getStringArray(R.array.app_icons);
        for (String temp : icons) {
            String str[] = temp.split("@");
            mIconMap.put(str[0], str[1]);
        }
    }

    public static List<AppInfo> getAllAppList() {
        try {
            OrderList r = new OrderList();
            Collections.sort(mAppList, r);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mAppList;
    }

    public static AppInfo getInfoByPkg(String pkg) {
        if (TextUtils.isEmpty(pkg) || isLoading) {
            return null;
        }
        for (AppInfo info : mAppList) {
            if (pkg.equals(info.packagename)) {
                return info;
            }
        }
        return null;
    }

    static class OrderList implements Comparator<AppInfo> {
        @Override
        public int compare(AppInfo o1, AppInfo o2) {
            String pkg1 = o1.getPackagename();
            String pkg2 = o2.getPackagename();
            if (UbtCantans.POWER_CLOCK_PKG.endsWith(pkg1)) {
                return -1;
            }
            if (UbtCantans.POWER_CLOCK_PKG.endsWith(pkg2)) {
                return 1;
            }
            boolean isCus1 = isCustomApp(pkg1);
            boolean isCus2 = isCustomApp(pkg2);
            if (isCus1 && isCus2) {
                return 0;
            }
            if (isCus1) {
                return -1;
            }
            if (isCus2) {
                return 1;
            }
            boolean isSystemApp1 = o1.isSystemApp;
            boolean isSystemApp2 = o2.isSystemApp;


            if (isSystemApp1 && isSystemApp2) {
                int index1 = firstList.indexOf(pkg1);
                int index2 = filterlist.indexOf(pkg2);
                if (index1 >= 0) {
                    if (index2 >= 0) {
                        return index2 - index1;
                    } else {
                        return -1;
                    }
                } else {
                    if (index2 >= 0) {
                        return -1;
                    } else {
                        return 0;
                    }
                }
            }
            if (isSystemApp1) {
                return -1;
            }
            if (isSystemApp2) {
                return 1;
            }
            return 0;
        }
    }

    private static boolean isCustomApp(String pkg) {
        return customizationlist.contains(pkg);
    }

    public static boolean isSystemApp(Context context, String pname) {
        if (context == null || TextUtils.isEmpty(pname)) {
            return false;
        }
        try {
            PackageInfo pInfo = context.getPackageManager().getPackageInfo(pname, 0);
            return isSystemApp(pInfo) || isSystemUpdateApp(pInfo);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return false;
    }

    private static boolean isSystemApp(PackageInfo pInfo) {
        return ((pInfo.applicationInfo.flags & android.content.pm.ApplicationInfo.FLAG_SYSTEM) != 0);
    }

    private static boolean isSystemUpdateApp(PackageInfo pInfo) {
        return ((pInfo.applicationInfo.flags & android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
    }
}
